Load data
Maps data
We use three different shapefiles for the continental U.S. land mass, the State waters of maine, new hampshire, massachusets, connecticut, rhode island, new york, new jersey, delaware, maryland, virginia, north carolina and the North East EEZ.
1.- Land shapefile; covers the US land territory for visualization. Data provided from the map package.
2.- State waters; covers the state waters of the NE US states. Data from data.gov.
License: No license information was provided. If this work was prepared by an officer or employee of the United States government as part of that person’s official duties it is considered a U.S. Government Work.
3.- EEZ shapefile; Used the Sea Around Us shapefle updated to June 2016.
unique(land_sf$ID)
Spatial component
Create base shapefile for computation
As a first step we need to divide the NE US EEZ among the different states. For that we expanded state waters up to the 200 nautical miles to then estimate the percentage that each expanded-state-waters occupied. Note that in all cases these areas overlapped and percentages accounted for it. We did this by following these steps:
- Expand state waters using a buffer
- Grid that buffer on a 0.3 resolution
- Crop the buffer to the EEZ
1. Expand Spatial regions (a.k.a buffers)
We set a buffer of 410000 m (410 km, ~ 221 nm) that overshoots the EEZ a bit, but is eventually cropped
# Buffer state waters
state_bf = st_buffer(state_sf, 410000) %>%
st_transform(4326) %>% # to match shape
st_set_crs(4326)
# ------------------------------ #
# Testing and visualizing the buffer
# ------------------------------ #
state_bf_plot <- ggplot() +
geom_sf(data = eez_sf, aes(), fill = NA) +
geom_sf(data = state_bf, aes(color = state), fill = NA)
#
# ggsave("../Results/Partial/state_waters_buffer.png",state_bf_plot)
# ------------------------------ #
state_bf_plot

2. Expand grid within buffer
Here we expand a grid within the buffer so we can estimate the proportion of each state

2.1 Merge grid and buffers
Once we have a gridded area, we converted the grid to a sf so we can merge it with the buffered states and finally filter out everything outside the states polygon
# ---------------- #
# Convert grid to sf
# ---------------- #
grid_sf <- st_as_sf(ne_grid,
coords = c("lon", "lat"),
crs = 4326) %>%
st_join(state_bf) %>%
filter(!is.na(state))
# Create data frame for future computations
# Note, will be used in next chunk
grid_bf_dt <- as.data.frame(grid_sf) %>%
select(index,state)
# group_by(state) %>%
# summarise(length(index))
# ---------------- #
# [TEST]
# Visualization of grid
# ---------------- #
gridExtra::grid.arrange(
# Overall (overlapping) position
ggplot(grid_sf) +
geom_sf(aes(color = state), alpha = 0.3) +
geom_sf(data = eez_sf, aes(),fill =NA) +
theme(legend.position = ""),
# Showing each state separatley
ggplot() +
geom_sf(data = grid_sf, aes(color = state),size = 0.1, alpha = 0.3) +
facet_wrap(~state) +
theme(legend.position = "top"),
nrow = 1)

3. Crop buffers to EEZ
Finally, we crop the grided buffers to within the EEZ to capture the actual water space.
Note: This step takes quite a while because of the size of the EEZ shapefile. No, you cannot use st_simplify() here

Interpolation rutine
Here we interpolate the survey data within the previously created grid.
- We removed cases where
wtcpue < 0
Function for interpolation
This is the main function used to interpolate the data per year. It follows a Triangular Irregular Surface method using the interp::interp() function.
Ocean adapt data
- Using only the Northeast US Fall and Spring bottom trawl survey data for now

Control Pannel
Load required data. Note that some of it has been previously created
# Load grid df
grid_eez_df <- my_path("D","Spatial","grid_eez_df.csv", read = T)
# Run interpolation for all years
years <- seq(1973,2019,1)
# taxa
spp <- "Centropristis striata"
# regions
regions <- c("Northeast US Fall" , "Northeast US Spring")
Run routine
Extrapolated data
| index |
state |
year |
region |
spp |
lon |
lat |
value |
| 73 |
north carolina |
1973 |
Northeast US Fall |
Centropristis striata |
-79.85582 |
30.94383 |
NA |
| 74 |
north carolina |
1973 |
Northeast US Fall |
Centropristis striata |
-79.55582 |
30.94383 |
NA |
| 75 |
north carolina |
1973 |
Northeast US Fall |
Centropristis striata |
-79.25582 |
30.94383 |
NA |
| 76 |
north carolina |
1973 |
Northeast US Fall |
Centropristis striata |
-78.95582 |
30.94383 |
NA |
| 77 |
north carolina |
1973 |
Northeast US Fall |
Centropristis striata |
-78.65582 |
30.94383 |
NA |
| 78 |
north carolina |
1973 |
Northeast US Fall |
Centropristis striata |
-78.35582 |
30.94383 |
NA |
| 79 |
north carolina |
1973 |
Northeast US Fall |
Centropristis striata |
-78.05582 |
30.94383 |
NA |
| 80 |
north carolina |
1973 |
Northeast US Fall |
Centropristis striata |
-77.75582 |
30.94383 |
NA |
| 81 |
north carolina |
1973 |
Northeast US Fall |
Centropristis striata |
-77.45582 |
30.94383 |
NA |
| 82 |
north carolina |
1973 |
Northeast US Fall |
Centropristis striata |
-77.15582 |
30.94383 |
NA |
Results
Points

Map

Area plot
This graph shows the proportion of each State over time
Area plot (running)
This graph shows the proportion of each State smoothed over a 10 years running mean. It helps seeing the trends better (I Think…)
LS0tCnRpdGxlOiAiU3BhdGlhbCBBbmFseXNpcyIKb3V0cHV0OiAKICMgaHRtbF9kb2N1bWVudAogIGh0bWxfbm90ZWJvb2s6CiAgZmlnX3dpZHRoOiA2CiAgZmlnX2hlaWdodDogNAogIHRvYzogZmFsc2UKICB0b2NfZGVwdGg6IDMKICBjb2RlX2ZvbGRpbmc6IGhpZGUKICB0b2NfZmxvYXQ6CiAgICBjb2xsYXBzZWQ6IGZhbHNlCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoTXlGdW5jdGlvbnMpCk15RnVuY3Rpb25zOjpteV9saWIoYygiZ2dtYXAiLCJzZiIsInRpZHl2ZXJzZSIsInRvb2xzIiwicmVhZHIiLCJkYXRhLnRhYmxlIiwibWFwcyIsInZpcmlkaXMiLCJ3ZXNhbmRlcnNvbiIsImtuaXRyIiwia2FibGVFeHRyYSIsInBsb3RseSIpKQpgYGAKCgojIExvYWQgZGF0YQoKIyMgTWFwcyBkYXRhCgpXZSB1c2UgdGhyZWUgZGlmZmVyZW50IHNoYXBlZmlsZXMgZm9yIHRoZSBjb250aW5lbnRhbCBVLlMuIGxhbmQgbWFzcywgdGhlIFN0YXRlIHdhdGVycyBvZiBtYWluZSwgbmV3IGhhbXBzaGlyZSwgbWFzc2FjaHVzZXRzLCBjb25uZWN0aWN1dCwgcmhvZGUgaXNsYW5kLCBuZXcgeW9yaywgbmV3IGplcnNleSwgZGVsYXdhcmUsIG1hcnlsYW5kLCB2aXJnaW5pYSwgbm9ydGggY2Fyb2xpbmEgYW5kIHRoZSBOb3J0aCBFYXN0IEVFWi4KCjEuLSAqKkxhbmQgc2hhcGVmaWxlOyoqIGNvdmVycyB0aGUgVVMgbGFuZCB0ZXJyaXRvcnkgZm9yIHZpc3VhbGl6YXRpb24uIERhdGEgcHJvdmlkZWQgZnJvbSB0aGUgYG1hcGAgcGFja2FnZS4KCjIuLSAqKlN0YXRlIHdhdGVyczsqKiBjb3ZlcnMgdGhlIHN0YXRlIHdhdGVycyBvZiB0aGUgTkUgVVMgc3RhdGVzLiBEYXRhIGZyb20gW2RhdGEuZ292XShodHRwczovL2NhdGFsb2cuZGF0YS5nb3YvZGF0YXNldC9mZWRlcmFsLWFuZC1zdGF0ZS13YXRlcnMpLiAgCgoqTGljZW5zZTogTm8gbGljZW5zZSBpbmZvcm1hdGlvbiB3YXMgcHJvdmlkZWQuIElmIHRoaXMgd29yayB3YXMgcHJlcGFyZWQgYnkgYW4gb2ZmaWNlciBvciBlbXBsb3llZSBvZiB0aGUgVW5pdGVkIFN0YXRlcyBnb3Zlcm5tZW50IGFzIHBhcnQgb2YgdGhhdCBwZXJzb24ncyBvZmZpY2lhbCBkdXRpZXMgaXQgaXMgY29uc2lkZXJlZCBhIFUuUy4gR292ZXJubWVudCBXb3JrLioKCjMuLSAqKkVFWiBzaGFwZWZpbGU7KiogVXNlZCB0aGUgKlNlYSBBcm91bmQgVXMqIHNoYXBlZmxlIHVwZGF0ZWQgdG8gSnVuZSAyMDE2LgoKYGBge3IgbWFwc19zZiwgZXZhbCA9IFQsIGVjaG8gPSBULCByZXN1bHRzID0gJ2hpZGUnfQoKU3RhdGVzIDwtIGMoIm1haW5lIiwgIm5ldyBoYW1wc2hpcmUiLCAibWFzc2FjaHVzZXR0cyIsICJjb25uZWN0aWN1dCIsICJyaG9kZSBpc2xhbmQiLCAibmV3IHlvcmsiLCAibmV3IGplcnNleSIsICJkZWxhd2FyZSIsICJtYXJ5bGFuZCIsICJ2aXJnaW5pYSIsICJub3J0aCBjYXJvbGluYSIsInBlbm5zeWx2YW5pYSIpIAoKIyBVUyBTdGF0ZSBNYXAgKGxhbmQpCgpsYW5kX3NmIDwtIHN0X2FzX3NmKG1hcCgic3RhdGUiLCBwbG90ID0gRkFMU0UsIGZpbGwgPSBUUlVFKSkgJT4lIAogIGZpbHRlcihJRCAlaW4lIFN0YXRlcykgCgojIGdncGxvdCh1c19tYXApICsKICAjIGdlb21fc2YoKQoKIyBVUyBFRVogbWFwCgojIHBhdGhfd29ybGQgPC0gTXlGdW5jdGlvbnM6Om15X3BhdGgoIkciLCBleHRyYV9wYXRoID0gIlNwYXRpYWwvU0FVL1NBVV9TaGFwZWZpbGUiKQpwYXRoX3dvcmxkIDwtICJ+L0Rvd25sb2Fkcy9TQVVfU2hhcGVmaWxlIgoKIyBUaGUgRmlsZQpmbmFtX3dvcmxkIDwtICJTQVVFRVpfSnVseTIwMTUuc2hwIgoKIyBMb2FkIGl0IQplZXpfc2YgPC0gc3RfcmVhZChkc24gPSBwYXRoX3dvcmxkLAogICAgICAgICAgICAgICAgICAgICAgICBsYXllciA9ZmlsZV9wYXRoX3NhbnNfZXh0KGZuYW1fd29ybGQpKSAlPiUgCiAgcmVuYW1lKGVlel9uYW1lID0gTmFtZSkgJT4lIAogIHN0X3RyYW5zZm9ybShjcnMgPSA0MzI2KSAlPiUgIyA0MzI2CiAgc3Rfc2ltcGxpZnkocHJlc2VydmVUb3BvbG9neSA9IFRSVUUsIGRUb2xlcmFuY2UgPSAxMDAwMCkgJT4lICMwLjEgZm9yIHBhcGVyCiAgZmlsdGVyKGVlel9uYW1lID09ICJVU0EgKEVhc3QgQ29hc3QpIikKCgojIGdncGxvdChlZXpfc2YpICsKIyBnZW9tX3NmKGFlcygpLGZpbGwgPU5BKQoKIyBnZ3Bsb3QoKSArCiMgICBnZW9tX3NmKGRhdGEgPSBXb3JsZF9lZXpfc2YsIGFlcygpLCBjb2xvciA9ICJyZWQiKSArCiMgICBnZW9tX3NmKGRhdGEgPSB1c19tYXAsIGFlcygpLCBjb2xvciA9ICJibHVlIikKCiMgVVMgc3RhdGUgd2F0ZXJzCiMgaHR0cHM6Ly9jYXRhbG9nLmRhdGEuZ292L2RhdGFzZXQvZmVkZXJhbC1hbmQtc3RhdGUtd2F0ZXJzCgojIHVzX3N0YXRlX3cgPC0gcmdkYWw6OnJlYWRPR1IoZHNuID0gIn4vRG93bmxvYWRzL0ZlZGVyYWxBbmRTdGF0ZVdhdGVycy9GZWRlcmFsQW5kU3RhdGVXYXRlcnMuZ2RiIikKc3RhdGVfc2YgPC0gIHN0X3JlYWQoIn4vRG93bmxvYWRzL0ZlZGVyYWxBbmRTdGF0ZVdhdGVycy9GZWRlcmFsQW5kU3RhdGVXYXRlcnMuZ2RiIikgJT4lCiAgamFuaXRvcjo6Y2xlYW5fbmFtZXMoKSAlPiUgCiAgbXV0YXRlKGp1cmlzZGljdGkgPSBzdHJfdG9fbG93ZXIoanVyaXNkaWN0aSkpICU+JSAKICBmaWx0ZXIoanVyaXNkaWN0aSAlaW4lIFN0YXRlcykgJT4lIAogIHJlbmFtZShzdGF0ZSA9IGp1cmlzZGljdGkpICU+JSAKICAjIHN0X3RyYW5zZm9ybShjcnMgPSA0MzI2KSAgIyBmb3IgbWF0Y2hpbmcgcHJvamVjdGlvbnMKICBzdF9zaW1wbGlmeShwcmVzZXJ2ZVRvcG9sb2d5ID0gVFJVRSwgZFRvbGVyYW5jZSA9IDEwMDAwKSAjMC4xIGZvciBwYXBlcgoKCmdyaWRfc2YgPC0gIHN0X3JlYWQoIi9Wb2x1bWVzL0VudGVycHJpc2UvRGF0YS9BY3Jvc3NCb3VuZGFyaWVzL0RhdGEvU3BhdGlhbC9ncmlkX3NmL2dyaWRfZWV6X3NmLnNocCIpCgp1bmlxdWUobGFuZF9zZiRJRCkKCmBgYAoKCiMjIFNwYXRpYWwgY29tcG9uZW50CgojIyMgQ3JlYXRlIGJhc2Ugc2hhcGVmaWxlIGZvciBjb21wdXRhdGlvbgoKQXMgYSBmaXJzdCBzdGVwIHdlIG5lZWQgdG8gZGl2aWRlIHRoZSBORSBVUyBFRVogYW1vbmcgdGhlIGRpZmZlcmVudCBzdGF0ZXMuIEZvciB0aGF0IHdlIGV4cGFuZGVkIHN0YXRlIHdhdGVycyB1cCB0byB0aGUgMjAwIG5hdXRpY2FsIG1pbGVzIHRvIHRoZW4gZXN0aW1hdGUgdGhlIHBlcmNlbnRhZ2UgdGhhdCBlYWNoIGV4cGFuZGVkLXN0YXRlLXdhdGVycyBvY2N1cGllZC4gTm90ZSB0aGF0IGluIGFsbCBjYXNlcyB0aGVzZSBhcmVhcyBvdmVybGFwcGVkIGFuZCBwZXJjZW50YWdlcyBhY2NvdW50ZWQgZm9yIGl0LiBXZSBkaWQgdGhpcyBieSBmb2xsb3dpbmcgdGhlc2Ugc3RlcHM6CgotIDEuIEV4cGFuZCBzdGF0ZSB3YXRlcnMgdXNpbmcgYSBidWZmZXIKCi0gMi4gR3JpZCB0aGF0IGJ1ZmZlciBvbiBhIDAuMyByZXNvbHV0aW9uCgotIDMuIENyb3AgdGhlIGJ1ZmZlciB0byB0aGUgRUVaCgojIyMjIDEuIEV4cGFuZCBTcGF0aWFsIHJlZ2lvbnMgKGEuay5hICBidWZmZXJzKQoKV2Ugc2V0IGEgYnVmZmVyIG9mICo0MTAwMDAqIG0gKDQxMCBrbSwgfiAyMjEgbm0pIHRoYXQgb3ZlcnNob290cyB0aGUgRUVaIGEgYml0LCBidXQgaXMgZXZlbnR1YWxseSBjcm9wcGVkCgpgYGB7ciBidWZmZXIsIGV2YWwgPSBULCBlY2hvID0gVH0KCiMgQnVmZmVyIHN0YXRlIHdhdGVycwpzdGF0ZV9iZiA9IHN0X2J1ZmZlcihzdGF0ZV9zZiwgNDEwMDAwKSAlPiUgCiAgc3RfdHJhbnNmb3JtKDQzMjYpICU+JSAjIHRvIG1hdGNoIHNoYXBlCiAgc3Rfc2V0X2Nycyg0MzI2KQoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gIwojIFRlc3RpbmcgYW5kIHZpc3VhbGl6aW5nIHRoZSBidWZmZXIgCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICMKCnN0YXRlX2JmX3Bsb3QgPC0gZ2dwbG90KCkgKwogIGdlb21fc2YoZGF0YSA9IGVlel9zZiwgYWVzKCksIGZpbGwgPSBOQSkgKwogIGdlb21fc2YoZGF0YSA9IHN0YXRlX2JmLCBhZXMoY29sb3IgPSBzdGF0ZSksIGZpbGwgPSBOQSkKIyAgIAoKIyBnZ3NhdmUoIi4uL1Jlc3VsdHMvUGFydGlhbC9zdGF0ZV93YXRlcnNfYnVmZmVyLnBuZyIsc3RhdGVfYmZfcGxvdCkKCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICMKCnN0YXRlX2JmX3Bsb3QKCmBgYAoKIyMjIyAyLiBFeHBhbmQgZ3JpZCB3aXRoaW4gYnVmZmVyCgpIZXJlIHdlIGV4cGFuZCBhIGdyaWQgd2l0aGluIHRoZSBidWZmZXIgc28gd2UgY2FuIGVzdGltYXRlIHRoZSBwcm9wb3J0aW9uIG9mIGVhY2ggc3RhdGUKCmBgYHtyIGdyaWRfaW5kZXhpbmcsIGV2YWwgPSBULCBlY2hvID0gVCwgbWVzc2FnZSA9IEYsIHdhcm5pbmcgPSBGfQoKIyBDcmVhdGUgZ3JpZCBvZiB0aGUgcmVnaW9uCmJib3ggPC0gYyhzdF9iYm94KHN0YXRlX2JmKSkKCiMgRXhwYW5kIHRoZSBncmlkCm5lX2dyaWQgPC0gZXhwYW5kLmdyaWQoCiAgICBsb24gPSBzZXEoZnJvbSA9IGJib3hbInhtaW4iXSwgdG8gPSBiYm94WyJ4bWF4Il0sIGJ5ID0gMC4zKSwKICAgIGxhdCA9IHNlcShmcm9tID0gYmJveFsieW1pbiJdLCB0byA9IGJib3hbInltYXgiXSwgYnkgPSAwLjMpCikgJT4lIAogIHJvd2lkX3RvX2NvbHVtbigiaW5kZXgiKQoKIyAtLS0tLS0tLS0tLSAjCiMgW1RFU1RdIFBsb3QgYWxsIGxheWVycwojIC0tLS0tLS0tLS0tICMKCiMgTG9va3MgZ29vZApzdGF0ZV9zZiAlPiUKICBzdF90cmFuc2Zvcm0oNDMyNikgJT4lICMgdG8gbWF0Y2ggc2hhcGUKICBzdF9zZXRfY3JzKDQzMjYpICU+JQogIHN0X3NpbXBsaWZ5KHByZXNlcnZlVG9wb2xvZ3kgPSBUUlVFLCBkVG9sZXJhbmNlID0gMTAwMDApICU+JQogIGdncGxvdCgpICsKICBnZW9tX3NmKGFlcyhjb2xvciA9IHN0YXRlKSkrCiAgIyBnZW9tX3NmKGRhdGEgPSBlZXpfc2YsIGFlcygpLGZpbGwgPU5BKSArCiAgIyBnZ3Bsb3QoKSsKICBnZW9tX3RpbGUoZGF0YSA9IG5lX2dyaWQsCiAgICAgICAgICAgIGFlcygKICAgICAgICAgICAgICB4ID0gbG9uLAogICAgICAgICAgICAgIHkgPSBsYXQKICAgICAgICAgICAgKSwKICAgICAgICAgICAgYWxwaGEgPSAwLjIKICApIAoKCmBgYAoKIyMjIyMgMi4xIE1lcmdlIGdyaWQgYW5kIGJ1ZmZlcnMKCk9uY2Ugd2UgaGF2ZSBhIGdyaWRkZWQgYXJlYSwgd2UgY29udmVydGVkIHRoZSBncmlkIHRvIGEgYHNmYCBzbyB3ZSBjYW4gbWVyZ2UgaXQgd2l0aCB0aGUgYnVmZmVyZWQgc3RhdGVzIGFuZCBmaW5hbGx5IGZpbHRlciBvdXQgZXZlcnl0aGluZyBvdXRzaWRlIHRoZSBzdGF0ZXMgcG9seWdvbgoKYGBge3IgZ3JpZF9idWZfbWVyZ2UsIGV2YWwgPSBULCBlY2hvID0gVCwgbWVzc2FnZSA9IEYsIHdhcm5pbmcgPSBGLCBmaWcud2lkdGggPSAxMH0KCiMgLS0tLS0tLS0tLS0tLS0tLSAjCiMgQ29udmVydCBncmlkIHRvIHNmCiMgLS0tLS0tLS0tLS0tLS0tLSAjCmdyaWRfc2YgPC0gc3RfYXNfc2YobmVfZ3JpZCwKICAgICAgICAgICAgIGNvb3JkcyA9IGMoImxvbiIsICJsYXQiKSwKICAgICAgICAgICAgIGNycyA9IDQzMjYpICU+JSAKICBzdF9qb2luKHN0YXRlX2JmKSAlPiUgCiAgZmlsdGVyKCFpcy5uYShzdGF0ZSkpCgojIENyZWF0ZSBkYXRhIGZyYW1lIGZvciBmdXR1cmUgY29tcHV0YXRpb25zCiMgTm90ZSwgd2lsbCBiZSB1c2VkIGluIG5leHQgY2h1bmsKZ3JpZF9iZl9kdCA8LSBhcy5kYXRhLmZyYW1lKGdyaWRfc2YpICU+JQogICAgc2VsZWN0KGluZGV4LHN0YXRlKQogICAgIyBncm91cF9ieShzdGF0ZSkgJT4lIAogICAgIyBzdW1tYXJpc2UobGVuZ3RoKGluZGV4KSkKCgojIC0tLS0tLS0tLS0tLS0tLS0gIwojIFtURVNUXSAKIyBWaXN1YWxpemF0aW9uIG9mIGdyaWQKIyAtLS0tLS0tLS0tLS0tLS0tICMKCmdyaWRFeHRyYTo6Z3JpZC5hcnJhbmdlKAogICMgT3ZlcmFsbCAob3ZlcmxhcHBpbmcpIHBvc2l0aW9uCiAgZ2dwbG90KGdyaWRfc2YpICsKICAgIGdlb21fc2YoYWVzKGNvbG9yID0gc3RhdGUpLCBhbHBoYSA9IDAuMykgKwogICAgZ2VvbV9zZihkYXRhID0gZWV6X3NmLCBhZXMoKSxmaWxsID1OQSkgKyAKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICIiKSwKICAjIFNob3dpbmcgZWFjaCBzdGF0ZSBzZXBhcmF0bGV5CiAgZ2dwbG90KCkgKwogICAgZ2VvbV9zZihkYXRhID0gZ3JpZF9zZiwgYWVzKGNvbG9yID0gc3RhdGUpLHNpemUgPSAwLjEsIGFscGhhID0gMC4zKSArCiAgICBmYWNldF93cmFwKH5zdGF0ZSkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpLAogIG5yb3cgPSAxKQoKYGBgCgojIyMjIDMuIENyb3AgYnVmZmVycyB0byBFRVoKCkZpbmFsbHksIHdlIGNyb3AgdGhlIGdyaWRlZCBidWZmZXJzIHRvIHdpdGhpbiB0aGUgRUVaIHRvIGNhcHR1cmUgdGhlIGFjdHVhbCB3YXRlciBzcGFjZS4KCipOb3RlOiogVGhpcyBzdGVwIHRha2VzIHF1aXRlIGEgd2hpbGUgYmVjYXVzZSBvZiB0aGUgc2l6ZSBvZiB0aGUgRUVaIHNoYXBlZmlsZS4gTm8sIHlvdSBjYW5ub3QgdXNlIGBzdF9zaW1wbGlmeSgpYCBoZXJlCgpgYGB7ciBidWZmX3RvX2VleiwgZXZhbCA9VCwgZWNobyA9IFQsIG1lc3NhZ2UgPSBGLCB3YXJuaW5nID0gRn0KCgojIEkgZG9uJ3Qga25vdyBob3cgdG8gdW5kbyBzdF9zaW1wbGlmeSBzbyBuZWVkIHRvIHJlLWxvYWQgdGhlIHNoYXBlZmlsZQplZXpfc2YgPC0gc3RfcmVhZChkc24gPSBwYXRoX3dvcmxkLAogICAgICAgICAgICAgICAgICAgICAgICBsYXllciA9ZmlsZV9wYXRoX3NhbnNfZXh0KGZuYW1fd29ybGQpKSAlPiUgCiAgcmVuYW1lKGVlel9uYW1lID0gTmFtZSkgJT4lIAogIHN0X3RyYW5zZm9ybShjcnMgPSA0MzI2KSAlPiUgIyA0MzI2CiAgZmlsdGVyKGVlel9uYW1lID09ICJVU0EgKEVhc3QgQ29hc3QpIikKCiMgR2V0IHRoZSBvdmVybGFwcGluZyBzZWdtZW50cwpncmlkX2Vlel9zZiA8LSBzdF9pbnRlcnNlY3Rpb24oZ3JpZF9zZixlZXpfc2YpCgojIHdyaXRlX3NmKGdyaWRfZWV6X3NmLCBwYXN0ZTAobXlfcGF0aCgiRCIsICJTcGF0aWFsIiksImdyaWRfZWV6X3NmLnNocCIpKQoKIyBHZXQgZmluYWwgZGYgd2l0aCBpbmRleApncmlkX2Vlel9kZiA8LSBhcy5kYXRhLmZyYW1lKGdyaWRfZWV6X3NmKSAlPiUKICBzZWxlY3Qoc3RhdGUsaW5kZXgpICU+JSAKICBsZWZ0X2pvaW4obmVfZ3JpZCwgCiAgICAgICAgICAgIGJ5ID0gImluZGV4IikKCiMgd3JpdGVfY3N2KGdyaWRfZWV6X2RmLCBwYXN0ZTAobXlfcGF0aCgiUiIsICJQYXJ0aWFsIiksImdyaWRfZWV6X2RmLmNzdiIpKQoKIyBQbG90IHRvIG1ha2Ugc3VyZSBtYWtlcyBzZW5zZSAoUGljYXNzbyBzeWxlKQpncmlkX2Vlel9zZiAlPiUKICBzdF9zaW1wbGlmeShwcmVzZXJ2ZVRvcG9sb2d5ID0gVFJVRSwgZFRvbGVyYW5jZSA9IDEwMDAwKSAlPiUgIzAuMSBmb3IgcGFwZXIKICBnZ3Bsb3QoKSArCiAgZ2VvbV9zZihhZXMoY29sb3IgPSBzdGF0ZSksIGFscGhhID0gMC4zKQoKYGBgCgojIyBJbnRlcnBvbGF0aW9uIHJ1dGluZQoKSGVyZSB3ZSBbaW50ZXJwb2xhdGVdKGh0dHBzOi8vc3dpbGtlLWdlb3NjaWVuY2UubmV0L3Bvc3Qvc3BhdGlhbF9pbnRlcnBvbGF0aW9uLykgdGhlIHN1cnZleSBkYXRhIHdpdGhpbiB0aGUgcHJldmlvdXNseSBjcmVhdGVkIGdyaWQuCgotIFdlIHJlbW92ZWQgY2FzZXMgd2hlcmUgYHd0Y3B1ZSA8IDBgCgojIyMgRnVuY3Rpb24gZm9yIGludGVycG9sYXRpb24KClRoaXMgaXMgdGhlIG1haW4gZnVuY3Rpb24gdXNlZCB0byBpbnRlcnBvbGF0ZSB0aGUgZGF0YSBwZXIgeWVhci4gSXQgZm9sbG93cyBhIFRyaWFuZ3VsYXIgSXJyZWd1bGFyIFN1cmZhY2UgbWV0aG9kIHVzaW5nIHRoZSBgaW50ZXJwOjppbnRlcnAoKWAgZnVuY3Rpb24uCgpgYGB7ciBpbnRlcnBvbF9mdW5jdGlvbiwgZXZhbCA9IFQsIGVjaG8gPSBUfQoKdGlzIDwtIGZ1bmN0aW9uKGlucHV0X2RhdGEsIGdyaWQsIHlyLCB0YXhhLCByZWcpewogIAogICMgcHJpbnQocGFzdGUoeXIpKQogIAogIGRhdGEgPC0gaW5wdXRfZGF0YSAlPiUgCiAgICBmaWx0ZXIoeWVhciA9PSB5ciwKICAgICAgICAgICBzcHAgPT0gdGF4YSwKICAgICAgICAgICByZWdpb24gPT0gcmVnCiAgICApICU+JSAKICAgIGZpbHRlcih3dGNwdWUgPiAwKQogICAgCiAgICBpZihucm93KGRhdGEpID09IDApewogICAgICByZXR1cm4odGliYmxlKCkpCiAgICB9ZWxzZXsKICAgICAgCiAgICAgICMgVHJpYW5ndWxhciBJcnJlZ3VsYXIgU3VyZmFjZQogICAgICBmaXRfdGluIDwtIGludGVycDo6aW50ZXJwKCAjIHVzaW5nIHtpbnRlcnB9CiAgICAgICAgeCA9IGRhdGEkbG9uLCAgICAgICAgICAgIyB0aGUgZnVuY3Rpb24gYWN0dWFsbHkgYWNjZXB0cyBjb29yZGluYXRlIHZlY3RvcnMKICAgICAgICB5ID0gZGF0YSRsYXQsCiAgICAgICAgeiA9IGRhdGEkd3RjcHVlLAogICAgICAgIHhvID0gZ3JpZCRsb24sICAgICAjIGhlcmUgd2UgYWxyZWFkeSBkZWZpbmUgdGhlIHRhcmdldCBncmlkCiAgICAgICAgeW8gPSBncmlkJGxhdCwKICAgICAgICBvdXRwdXQgPSAicG9pbnRzIgogICAgICApICU+JSAKICAgICAgICBiaW5kX2NvbHMoKSAlPiUgCiAgICAgICAgYmluZF9jb2xzKGdyaWQpICU+JQogICAgICAgIG11dGF0ZSh5ZWFyID0geXIsCiAgICAgICAgICAgICAgIHJlZ2lvbiA9IHJlZywKICAgICAgICAgICAgICAgc3BwID0gdGF4YSkgJT4lIAogICAgICAgIHNlbGVjdChpbmRleCwgc3RhdGUsIHllYXIsIHJlZ2lvbiwgc3BwLCBsb249eCwgbGF0PXksIHZhbHVlID0geikKICAgICAgCiAgICB9CiAgIAogICAgcmV0dXJuKGZpdF90aW4pCiAgfQoKYGBgCgojIyMgT2NlYW4gYWRhcHQgZGF0YQoKLSBVc2luZyBvbmx5IHRoZSBOb3J0aGVhc3QgVVMgRmFsbCBhbmQgU3ByaW5nIGJvdHRvbSB0cmF3bCBzdXJ2ZXkgZGF0YSBmb3Igbm93CgpgYGB7ciBkYXRfZXhwbG9kZWQsIGV2YWwgPSBULCBlY2hvID0gRn0KCm9jZWFuX2RhdGEgPC0gcmVhZFJEUygiL1ZvbHVtZXMvRW50ZXJwcmlzZS9EYXRhL3BpbnNreWxhYi1PY2VhbkFkYXB0LTk2NmFkZjAvZGF0YV9jbGVhbi9kYXRfZXhwbG9kZWQucmRzIikgIyU+JSAKICAjIGZpbHRlcihzcHAgPT0gIkNlbnRyb3ByaXN0aXMgc3RyaWF0YSIsCiAgICAgICAjIHJlZ2lvbiAlaW4lIGMoIk5vcnRoZWFzdCBVUyBGYWxsIiAsICJOb3J0aGVhc3QgVVMgU3ByaW5nIikpICNObyBtb3JlIHNlYXNvbnMKCnN1YnNldF9kYXRhIDwtIG9jZWFuX2RhdGEgJT4lIAogIGZpbHRlcihzcHAgPT0gIkNlbnRyb3ByaXN0aXMgc3RyaWF0YSIsCiAgICAgICByZWdpb24gJWluJSBjKCJOb3J0aGVhc3QgVVMgRmFsbCIgLCAiTm9ydGhlYXN0IFVTIFNwcmluZyIpCiAgICAgICApCgpnZ3Bsb3QoKSArCiAgZ2VvbV9wb2ludChkYXRhID0gc3Vic2V0KHN1YnNldF9kYXRhLCB3dGNwdWUgPSAwLjApLAogICAgICAgICAgICAgYWVzKAogICAgICAgICAgICAgICB4ID0gbG9uLAogICAgICAgICAgICAgICB5ID0gbGF0CiAgICAgICAgICAgICApLAogICAgICAgICAgICAgY29sb3IgPSAiZ3JleTk1IgogICkgKwogIGdlb21fcG9pbnQoZGF0YSA9IHN1YnNldChzdWJzZXRfZGF0YSwgd3RjcHVlID4gMCksCiAgICAgICAgICAgICBhZXMoCiAgICAgICAgICAgICAgIHggPSBsb24sCiAgICAgICAgICAgICAgIHkgPSBsYXQsCiAgICAgICAgICAgICAgIGNvbG9yID0gbG9nMTAod3RjcHVlKQogICAgICAgICAgICAgKSwKICAgICAgICAgICAgIHNpemUgPSAxCiAgKSArCiAgc2NhbGVfY29sb3JfZGlzdGlsbGVyKHBhbGV0dGUgPSAiU3BlY3RyYWwiLCAKICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGVfbGVnZW5kKHRpdGxlID0gIldDUFVFIHBlciBIYXVsIChsb2cxMCkiKSkgKyAKICBjb29yZF9zZih4bGltID0gYygtNzYsIC02NSkseWxpbSA9IGMoMzUsIDQ1KSkgKwogIE15RnVuY3Rpb25zOjpteV9nZ3RoZW1lX20oKSArCiAgZmFjZXRfd3JhcCh+cmVnaW9uKQoKYGBgCgojIyMgQ29udHJvbCBQYW5uZWwKCkxvYWQgcmVxdWlyZWQgZGF0YS4gTm90ZSB0aGF0IHNvbWUgb2YgaXQgaGFzIGJlZW4gcHJldmlvdXNseSBjcmVhdGVkIAoKYGBge3IgY29udHJvX3Bhbm5lbCwgZXZhbCA9IFQsIGVjaG8gPSBUfQoKIyBMb2FkIGdyaWQgZGYKZ3JpZF9lZXpfZGYgPC0gbXlfcGF0aCgiRCIsIlNwYXRpYWwiLCJncmlkX2Vlel9kZi5jc3YiLCByZWFkID0gVCkKCiMgUnVuIGludGVycG9sYXRpb24gZm9yIGFsbCB5ZWFycwp5ZWFycyA8LSBzZXEoMTk3MywyMDE5LDEpCgojIHRheGEKc3BwIDwtICJDZW50cm9wcmlzdGlzIHN0cmlhdGEiCgojIHJlZ2lvbnMKcmVnaW9ucyA8LSBjKCJOb3J0aGVhc3QgVVMgRmFsbCIgLCAiTm9ydGhlYXN0IFVTIFNwcmluZyIpCgpgYGAKCiMjIyBSdW4gcm91dGluZQoKYGBge3IgcnVuX3JvdXRpbmUsIGV2YWwgPSBULCBlY2hvID0gVH0KCiMgUnVuIGZvciBhIHNpbmdsZSByZWdpb24KIyBoaXN0b3JpY190aWYgPC0gYmluZF9yb3dzKAogICMgbGFwcGx5KHllYXJzLHRpcyxpbnB1dF9kYXRhID0gb2NlYW5fZGF0YSwgZ3JpZCA9IGdyaWQsIHRheGEgPSAiQ2VudHJvcHJpc3RpcyBzdHJpYXRhIiwgcmVnID0gcmVnaW9uc1syXSkKIyApCgoKIyBTaW1wbGUgZm9yLWxvb3AgZm9yIHJ1bm5pbmcgYm90aCByZWdpb25zIChzZWFzb25zKQpmb3IociBpbiAxOjIpewogIAogIHBhcnRpYWxfZGYgPC0gYmluZF9yb3dzKAogICAgbGFwcGx5KHllYXJzLHRpcyxpbnB1dF9kYXRhID0gb2NlYW5fZGF0YSwgZ3JpZCA9IGdyaWQsIHRheGEgPSBzcHAsIHJlZyA9IHJlZ2lvbnNbcl0pCiAgKQogIAogIGlmKHIgPT0gMSl7CiAgICBoaXN0b3JpY190aWYgPC0gcGFydGlhbF9kZgogIH1lbHNlewogICAgaGlzdG9yaWNfdGlmIDwtIGJpbmRfcm93cyhoaXN0b3JpY190aWYscGFydGlhbF9kZikKICB9CiAgCn0KCiMgU2F2ZSBkYXRhIGZvciBmdXR1cmUgcGxvdHRpbmcKIyB3cml0ZV9jc3YoaGlzdG9yaWNfdGlmLAogICAgICAgICAgIyBwYXN0ZTAobXlfcGF0aCgiUiIsIlBhcnRpYWwiKSwiaW50ZXJwb2xhdGVkX2RhdGEuY3N2IikpCgojIFNob3cgZGF0YSBpbiBub3RlYm9vawpoZWFkKGhpc3RvcmljX3RpZiwxMCkgJT4lIAogICBrYWJsZSgKICAgIGZvcm1hdCA9ICJodG1sIiwKICAgIGNhcHRpb24gPSAiRXh0cmFwb2xhdGVkIGRhdGEiKSAlPiUgCiAga2FibGVFeHRyYTo6a2FibGVfbWluaW1hbCgpICU+JSAKICBrYWJsZUV4dHJhOjprYWJsZV9zdHlsaW5nKCkgJT4lCiAga2FibGVFeHRyYTo6IHNjcm9sbF9ib3god2lkdGggPSAiMTAwJSIsIGhlaWdodCA9ICIzMDBweCIpCgpgYGAKCgojIFJlc3VsdHMKCgpgYGB7ciBsb2FkX2RhdGF9CgojIExvYWQgaW50ZXJwb2xhdGVkIGRhdGEKaGlzdG9yaWNfdGlmIDwtIG15X3BhdGgoIlIiLCJQYXJ0aWFsIiwiaW50ZXJwb2xhdGVkX2RhdGEuY3N2IixyZWFkID0gVCkKCiMgUGVyaW9kcwpwZXJpb2RzIDwtdGliYmxlKAogIHBlcmlvZCA9IGMocmVwKCJhIGVhcmx5IiwxMiksCiAgICAgICAgICAgICByZXAoImIgbWlkIiwxMiksCiAgICAgICAgICAgICByZXAoImMgbGF0ZSIsMTIpLAogICAgICAgICAgICAgcmVwKCJkIG5vdyIsMTIpCiAgICAgICAgICAgICApLAogIHllYXIgPSBjKHNlcSgxOTcyLDE5ODQsMSksCiAgICAgICAgICAgIHNlcSgxOTg1LDE5OTcsMSksCiAgICAgICAgICAgIHNlcSgxOTk4LDIwMTEsMSksCiAgICAgICAgICAgIHNlcSgyMDEyLDIwMTksMSkKICAgICAgICAgICAgKQogICkKCiMgU3RhdGUgcGFsbGV0CgpzdGF0ZV9wYWxsZXQgPC0gYyh3ZXNfcGFsZXR0ZShuID0gNSwgbmFtZSA9ICJEYXJqZWVsaW5nMSIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2VzX3BhbGV0dGUobiA9IDUsIG5hbWUgPSAiRGFyamVlbGluZzIiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdlc19wYWxldHRlKG4gPSAzLCBuYW1lID0gIlJveWFsMSIpCiAgICAgICAgICAgICAgICAgICkKCmBgYAoKCiMjIFBvaW50cwoKYGBge3IgYXJlYV9tYXBfc3RhdGUsIGV2YWwgPSBULCBlY2hvID0gVCwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTEyfQoKIGRhdGFfZ3JpZCA8LSBoaXN0b3JpY190aWYgJT4lIAogICMgbGVmdF9qb2luKHBlcmlvZHMpICU+JSAKICAjIGdyb3VwX2J5KHN0YXRlLGxhdCxsb24scGVyaW9kKSAlPiUgCiAgZ3JvdXBfYnkoc3RhdGUsbGF0LGxvbixyZWdpb24pICU+JSAKICBzdW1tYXJpc2UobWVhbiA9IG1lYW4odmFsdWUsbmEucm09IFQpLCAuZ3JvdXBzID0gImRyb3AiKSAlPiUgCiAgcmVuYW1lKElEID0gc3RhdGUpCgpnZ3Bsb3QoZGF0YV9ncmlkKSArCiAgZ2VvbV90aWxlKAogICAgYWVzKAogICAgICB4ID0gbG9uLAogICAgICB5ID0gbGF0LAogICAgICBmaWxsID0gbWVhbiwKICAgICAgY29sID0gbWVhbgogICAgKQogICkgKwogIGZhY2V0X3dyYXAofiBJRCAgKyAgcmVnaW9uLAogICAgICAgICAgICAgbmNvbCA9IDQpICsKICBzY2FsZV9maWxsX3ZpcmlkaXMoIk1lYW4gUHJvcG9ydGlvbiIsIGFscGhhID0gMC44KSArCiAgc2NhbGVfY29sb3JfdmlyaWRpcygiTWVhbiBQcm9wb3J0aW9uIiwgYWxwaGEgPSAwLjgpCgoKYGBgCgojIyBNYXAKCmBgYHtyIGFyZWFfbWFwLCBldmFsID0gVCwgZWNobyA9IFQsIGZpZy53aWR0aCA9IDEwfQoKdG90YWxfZml0ZWQgPC0gaGlzdG9yaWNfdGlmICU+JSAKICBncm91cF9ieSh5ZWFyLHJlZ2lvbikgJT4lIAogIHN1bW1hcmlzZSh0b3RhbF92YWx1ZSA9IHN1bSh2YWx1ZSxuYS5ybT1UKSkKCnN0YXRlX2ZpdCA8LSBoaXN0b3JpY190aWYgJT4lIAogIGdyb3VwX2J5KHN0YXRlLHllYXIscmVnaW9uKSAlPiUgCiAgc3VtbWFyaXNlKHN0YXRlX3ZhbHVlID0gc3VtKHZhbHVlLG5hLnJtPSBUKSwgLmdyb3VwcyA9ICJkcm9wIikgJT4lIAogIGxlZnRfam9pbih0b3RhbF9maXRlZCwKICAgICAgICAgICAgYnkgPSBjKCJ5ZWFyIiwicmVnaW9uIikpICU+JQogIG11dGF0ZShwZXJjZW50YWdlID0gc3RhdGVfdmFsdWUvdG90YWxfdmFsdWUqMTAwKSAlPiUgCiAgbGVmdF9qb2luKHBlcmlvZHMpICU+JSAKICBncm91cF9ieShJRCA9IHN0YXRlLHBlcmlvZCxyZWdpb24pICU+JSAKICBzdW1tYXJpc2UobWVhbl9wZXIgPSByb3VuZChtZWFuKHBlcmNlbnRhZ2UpKSkKICAKIyBjaGVjayBwZXJjZW50YWdlcwojIHN0YXRlX2ZpdCAlPiUgCiMgICBncm91cF9ieShwZXJpb2QpICU+JSAKIyAgIHN1bW1hcmlzZShzdW0obWVhbl9wZXIpKQoKCmxhbmRfc2YgJT4lIAogIGxlZnRfam9pbihzdGF0ZV9maXQsCiAgICAgICAgICAgIGJ5ID0gIklEIikgJT4lIAogIGdncGxvdCgpICsKICBnZW9tX3NmKGFlcyhmaWxsID0gbWVhbl9wZXIpKSArCiAgdmlyaWRpczo6c2NhbGVfZmlsbF92aXJpZGlzKCJNZWFuIFByb3BvcnRpb24iLCBhbHBoYSA9IDAuOCkgKwogIGZhY2V0X3dyYXAofnJlZ2lvbiArIHBlcmlvZCwgbnJvdyA9IDIpICsKICBteV9nZ3RoZW1lX20oKQoKYGBgCgojIyBBcmVhIHBsb3QKClRoaXMgZ3JhcGggc2hvd3MgdGhlIHByb3BvcnRpb24gb2YgZWFjaCBTdGF0ZSBvdmVyIHRpbWUKCmBgYHtyIGFyZWFfcGxvdCwgZXZhbCA9IFQsIGVjaG8gPSBULCBmaWcuaGVpZ2h0ID0gMTAsIGZpZy53aWR0aCA9IDEwfQoKdG90YWxfZml0ZWQgPC0gaGlzdG9yaWNfdGlmICU+JSAKICBncm91cF9ieSh5ZWFyLHJlZ2lvbikgJT4lIAogIHN1bW1hcmlzZSh0b3RhbF92YWx1ZSA9IHN1bSh2YWx1ZSxuYS5ybT1UKSkKCiMgZ3JvdXAgYnkgc3RhdGUKc3RhdGVfZml0IDwtIGhpc3RvcmljX3RpZiAlPiUgCiAgZ3JvdXBfYnkoc3RhdGUseWVhcixyZWdpb24pICU+JSAKICBzdW1tYXJpc2Uoc3RhdGVfdmFsdWUgPSBzdW0odmFsdWUsbmEucm09IFQpLCAuZ3JvdXBzID0gImRyb3AiKSAlPiUgCiAgbGVmdF9qb2luKHRvdGFsX2ZpdGVkLAogICAgICAgICAgICBieSA9IGMoInllYXIiLCJyZWdpb24iKSkgJT4lCiAgbXV0YXRlKHBlcmNlbnRhZ2UgPSBzdGF0ZV92YWx1ZS90b3RhbF92YWx1ZSoxMDApICU+JSAKICBncm91cF9ieShzdGF0ZSxyZWdpb24pCgpwIDwtIGdncGxvdChzdGF0ZV9maXQpICsKICBnZW9tX2FyZWEoCiAgICBhZXMoCiAgICAgIHggPSB5ZWFyLAogICAgICB5ID0gcm91bmQocGVyY2VudGFnZSksCiAgICAgIGZpbGwgPSBzdGF0ZQogICAgKQogICkgKwogIHlsYWIoIlBlcmNlbnRhZ2UgKCUpIikgKwogICMgdmlyaWRpczo6c2NhbGVfZmlsbF92aXJpZGlzKGRpc2NyZXRlID0gVCwgYWxwaGEgPSAwLjgpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBzdGF0ZV9wYWxsZXQpICsKICBNeUZ1bmN0aW9uczo6bXlfZ2d0aGVtZV9wKCkgKwogIGZhY2V0X3dyYXAofnJlZ2lvbiwgbmNvbCA9IDEpCgpnZ3Bsb3RseShwLAogICAgICAgICBkeW5hbWljVGlja3MgPSBUUlVFKSAlPiUgCiAgbGF5b3V0KGhvdmVybW9kZSA9ICJ4IikgJT4lIAogICMgYWRkX3RyYWNlKCkgJT4lIAogIHJhbmdlc2xpZGVyKCkKCmBgYAojIyBBcmVhIHBsb3QgKHJ1bm5pbmcpCgpUaGlzIGdyYXBoIHNob3dzIHRoZSBwcm9wb3J0aW9uIG9mIGVhY2ggU3RhdGUgc21vb3RoZWQgb3ZlciBhIDEwIHllYXJzIHJ1bm5pbmcgbWVhbi4gSXQgaGVscHMgc2VlaW5nIHRoZSB0cmVuZHMgYmV0dGVyIChJIFRoaW5rLi4uKQoKYGBge3IgYXJlYV9sbV9wbG90LCBldmFsID0gVCwgZWNobyA9IFQsIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoID0gMTB9CgojIGdyb3VwIGJ5IHN0YXRlCnN0YXRlX2ZpdCA8LSBoaXN0b3JpY190aWYgJT4lIAogIGdyb3VwX2J5KHN0YXRlLHllYXIscmVnaW9uKSAlPiUgCiAgc3VtbWFyaXNlKHN0YXRlX3ZhbHVlID0gc3VtKHZhbHVlLG5hLnJtPSBUKSwgLmdyb3VwcyA9ICJkcm9wIikgJT4lIAogIGxlZnRfam9pbih0b3RhbF9maXRlZCwKICAgICAgICAgICAgYnkgPSBjKCJ5ZWFyIiwicmVnaW9uIikpICU+JQogIG11dGF0ZShwZXJjZW50YWdlID0gc3RhdGVfdmFsdWUvdG90YWxfdmFsdWUqMTAwKSAlPiUgCiAgZ3JvdXBfYnkoc3RhdGUscmVnaW9uKSAlPiUgCiAgbXV0YXRlKFJNZWFuID0gem9vOjpyb2xsbWVhbih4ID0gcGVyY2VudGFnZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAxMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSBOQSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hLnJtPVQpCiAgICApCgojIFBsb3QgbWUKcCA8LSBnZ3Bsb3Qoc3RhdGVfZml0KSArCiAgZ2VvbV9hcmVhKAogICAgYWVzKAogICAgICB4ID0geWVhciwKICAgICAgeSA9IHJvdW5kKFJNZWFuKSwKICAgICAgZmlsbCA9IHN0YXRlCiAgICApCiAgKSArCiAgeWxhYigiMTAgeXJzIHJ1bm5pbmcgYXZlcmFnZSAoJSkiKSArCiAgIyB2aXJpZGlzOjpzY2FsZV9maWxsX3ZpcmlkaXMoZGlzY3JldGUgPSBULCBhbHBoYSA9IDAuOCkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHN0YXRlX3BhbGxldCkgKwogIE15RnVuY3Rpb25zOjpteV9nZ3RoZW1lX3AoKSArCiAgZmFjZXRfd3JhcCh+cmVnaW9uLCBuY29sID0gMSkKCnN1cHByZXNzV2FybmluZ3MoCmdncGxvdGx5KHAsCiAgICAgICAgIGR5bmFtaWNUaWNrcyA9IFRSVUUpICU+JSAKICBsYXlvdXQoaG92ZXJtb2RlID0gIngiKSAlPiUgCiAgIyBhZGRfdHJhY2UoKSAlPiUgCiAgcmFuZ2VzbGlkZXIoKQopCgpgYGAK